#include <algorithm>
#include <cmath>
#include "wingbox.h"

double wingbox::FailureSequenceIR(double pos, double spacing) const
{
	auto I(inertia(pos));
	auto c(poprivets.getEndFixity());
	auto sweep(getSweepFactor(pos));
	auto E(b.getMaterial().youngsmodulus);
	auto t(b.getThickness());
	auto y(abs(centroid(pos)));

	return (I * 0.9 * c * E *sqr(t / spacing) ) / (sweep * pos * y);

}

wingbox::FailSeqIRListTy wingbox::FailureSequenceIR() const
{
	FailSeqIRListTy results;
	for (auto iter(top_stringers.begin());iter != top_stringers.end(); ++iter) {
		const auto& sdata(*iter);
		const std::vector<double>& rivetlist(std::get<2>(sdata));
		std::vector<std::pair<int,  double> > sublist;
		if (rivetlist.size() > 1) {
			auto next(rivetlist.begin());
			auto current(next++);
			int i(0);
			while ( next != rivetlist.end()) {
				double p1(std::floor((*current)*1000 + 0.5));
				double p2(std::floor((*next)*1000+0.5));
				double spacing (std::abs(p1 - p2)/1000);

				sublist.push_back(std::make_pair(i, FailureSequenceIR(*current, spacing)));

				current = next++;
				++i;

			}
		}
		results.push_back(std::make_pair(iter, sublist));
	};
	return results;
}
double wingbox::FailureSequenceSheet(double pos, double spacing) const
{
	auto I(inertia(pos));
	auto Kc(getKc(pos));
	auto sweep(getSweepFactor(pos));
	auto E(b.getMaterial().youngsmodulus);
	auto t(b.getThickness());
	auto y(abs(centroid(pos)));

	return (I * Kc * E *sqr(t / spacing) ) / (sweep * pos * y);

}
std::vector<std::pair<wingbox::stringerlist::const_iterator, double> > wingbox::FailureSequenceSheet() const
{
	std::vector<std::pair<wingbox::stringerlist::const_iterator, double> > results;
	if (top_stringers.size() > 2) {
		auto next(top_stringers.begin());
		auto prev(next++);
		auto current(next++);
		while (next != top_stringers.end()) {
			const position& p(std::get<1>(*current));
			double spacing(calcSpaceWithout(current, p.x - std::get<0>(*current).getLength()));
			results.push_back(std::make_pair(current, FailureSequenceSheet(p.x - std::get<0>(*current).getLength(), spacing)));

			current = next++;
		}
	}
	return results;
}
std::vector<std::pair<wingbox::stringerlist::const_iterator, double> > wingbox::FailureSequenceSheetAtRoot() const
{
	std::vector<std::pair<wingbox::stringerlist::const_iterator, double> > results;
	if (top_stringers.size() > 1) {
		auto next(top_stringers.begin());
		auto current(next++);
		while (next != top_stringers.end()) {
			double p1(std::floor(std::get<1>(*current).y*1000 + 0.5));
			double p2(std::floor(std::get<1>(*next).y*1000 + 0.5));
			double spacing (std::abs(p1 - p2)/1000);
			const position& p(std::get<1>(*current));
			results.push_back(std::make_pair(current, FailureSequenceSheet(p.x, spacing)));

			current = next++;
		}
	}
	return results;
}
double wingbox::FailureSequenceBottom(double pos) const
{
	auto I(inertia(pos));
	auto sult(b.getMaterial().ultimatestress);
	auto sweep(getSweepFactor(pos));
	auto t(b.getThickness());
	auto y(abs(-b.getHeight() - centroid(pos)));

	return (I *  sult) / (sweep * pos * y);
}
std::pair<wingbox::stringer_const_iterator, double>  wingbox::FailureSequenceBottom() const
{
	auto maxiter(top_stringers.end());
	double p(0);
	for (auto iter(top_stringers.begin());iter != top_stringers.end(); ++iter) {
		double v(std::get<2>(*iter).front());
		if (v>p) {
			p = v;
			maxiter = iter;
		}
	}
	double LoadRoot(FailureSequenceBottom(b.getLength()));
	double LoadFirstRivet(FailureSequenceBottom(p)/3);
	if (LoadRoot < LoadFirstRivet) {
		return std::make_pair(top_stringers.end(), LoadRoot);
	} else {
		return std::make_pair(maxiter, LoadFirstRivet);
	}

}